package pe.com.bbva.efcap.servidor.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

import pe.com.bbva.efcap.servidor.dao.EntidadDAO;

public class EntidadDAOImpl<E> implements EntidadDAO<E>, Serializable {

	private static final long serialVersionUID = 1L;
	
	@Autowired
	private SessionFactory sessionFactory;

	protected Session getSession() throws HibernateException {
		return sessionFactory.getCurrentSession();
	}

	private Class<E> entityClass;

	public Serializable guardar(E e) {
		Serializable s = getSession().save(e);
		getSession().flush();
		return s;
	}
	
	public void eliminar(Object id) {
		getSession().delete(id);
		getSession().flush();
	}
	
	public void actualizar(E e) {
		getSession().update(e);
		getSession().flush();
	}

	public E buscarPorId(Object id) {
		return (E)getSession().get(getEntityClass().getName(), (Serializable) id);
	}

	public List<E> buscar() {
		return getSession().createQuery("from "+getEntityClass().getName()).list();
	}

	public Class<E> getEntityClass() {
		if (entityClass == null) {
			Type type = getClass().getGenericSuperclass();
			if (type instanceof ParameterizedType) {
				ParameterizedType paramType = (ParameterizedType) type;
				if (paramType.getActualTypeArguments().length == 2) {
					if (paramType.getActualTypeArguments()[1] instanceof TypeVariable) {
						throw new IllegalArgumentException("No se puede obtener clase mediante reflection");
					} else {
						entityClass = (Class<E>) paramType.getActualTypeArguments()[1];
					}
				} else {
					entityClass = (Class<E>) paramType.getActualTypeArguments()[0];
				}
			} else {
				throw new ClassCastException("No se puede obtener clase mediante reflection");
			}
		}
		return entityClass;	
	}

}
